package com.oliet.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.oliet.common.dto.user.CreateUserDTO;
import com.oliet.common.dto.user.ResetPasswordDTO;
import com.oliet.common.dto.user.UpdateUserDTO;
import com.oliet.common.vo.page.PageVO;
import com.oliet.common.vo.permission.PermissionTreeNodeVO;
import com.oliet.common.vo.role.RoleVO;
import com.oliet.common.vo.user.UserInfoVO;
import com.oliet.common.vo.user.UserVO;
import com.oliet.entity.RolePermissions;
import com.oliet.entity.UserRoles;
import com.oliet.entity.Users;
import com.oliet.entity.base.BaseEntity;
import com.oliet.exception.CustomException;
import com.oliet.exception.ErrorEnum;
import com.oliet.mapper.UserRolesMapper;
import com.oliet.mapper.UsersMapper;
import com.oliet.service.RolePermissionsService;
import com.oliet.service.UserRolesService;
import com.oliet.service.UsersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oliet.util.CodeUtils;
import com.oliet.util.PasswordUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author JZP
 * @since 2023-11-26
 */
@Transactional
@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements UsersService {

    @Autowired
    private UsersMapper usersMapper;
    @Autowired
    private UserRolesService userRolesService;
    @Autowired
    private RolePermissionsService rolePermissionsService;
    @Autowired
    private UserRolesMapper userRolesMapper;

    @Override
    public Users getByUsername(String username) {
        return this.usersMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getUsername, username));
    }

    @Override
    public String getUserAuthorityInfo(Long userId) {
        Users users = this.usersMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getId, userId));
        //TODO 查询真实的权限信息
        return "123,456";
    }

    @Override
    public void create(CreateUserDTO param) {
        //校验用户名
        this.verifyUsername(param.getUsername());
        //创建用户，并赋值属性
        Users po = new Users();
        BeanUtils.copyProperties(param, po);
        po.setCode(CodeUtils.getCommonCode());
        String encryptionPassword = PasswordUtils.generateEncryptionPassword(param.getPassword());
        po.setPassword(encryptionPassword);
        po.setIsSuperAdmin(false);
        //保存用户
        this.save(po);
        //保存用户角色表
        this.userRolesService.batchInsert(po.getId(), param.getRoleIds());
    }


    @Override
    public PageVO pageList(Long pageNo, Long pageSize, String search) {
        //分页查询
        Page<Users> page = new Page<>(pageNo, pageSize);
        Page<Users> poData = this.page(page, new LambdaQueryWrapper<Users>()
                .and(
                        StrUtil.isNotBlank(search),
                        wrapper -> wrapper.like(Users::getUsername, search)
                                .or()
                                .like(Users::getFullName, search)
                ).orderByDesc(BaseEntity::getDateCreated)
        );
        Map<Long, List<Long>> roleIdMap = getRoleIdMap(poData);
        List<UserVO> voList = UserVO.poListConverVoList(poData.getRecords(), roleIdMap);
        PageVO<UserVO> pageVo = new PageVO<>(poData.getCurrent(), poData.getSize(), poData.getTotal(), voList);
        return pageVo;
    }

    public Map<Long, List<Long>> getRoleIdMap(Page<Users> poData) {
        Map<Long, List<Long>> result = Maps.newHashMap();
        if (ObjectUtil.isNull(poData) || CollectionUtil.isEmpty(poData.getRecords())) {
            return result;
        }
        List<Long> ids = poData.getRecords().stream().map(BaseEntity::getId).collect(Collectors.toList());
        List<UserRoles> urList = this.userRolesMapper.selectList(new LambdaQueryWrapper<UserRoles>().in(UserRoles::getUserId, ids));
        result = urList.stream()
                .collect(Collectors.groupingBy(UserRoles::getUserId,
                        Collectors.mapping(UserRoles::getRoleId, Collectors.toList())));
        return result;
    }

    @Override
    public void resetPassword(ResetPasswordDTO param) {
        Users po = this.getUserByUsername(param.getUsername());
        //校验密码
        if (!PasswordUtils.matches(param.getPassword(), po.getPassword())) {
            throw new CustomException(ErrorEnum.PASSWORD_ERROR);
        } else {
            //重置密码
            String encryptionPassword = PasswordUtils.generateEncryptionPassword(param.getNewPassword());
            po.setPassword(encryptionPassword);
            this.updateById(po);
        }
    }

    @Override
    public void verifyUsername(String username) {
        long count = this.count(new LambdaQueryWrapper<Users>().eq(Users::getUsername, username));
        if (count > 0) {
            throw new CustomException(ErrorEnum.USERNAME_EXIST);
        }
    }

    @Override
    public void verifyPassword(String username, String password) {
        Users po = this.getUserByUsername(username);
        if (!PasswordUtils.matches(password, po.getPassword())) {
            throw new CustomException(ErrorEnum.PASSWORD_ERROR);
        }
    }

    @Override
    public UserInfoVO getInfo(Long id) {
        Users po = this.getById(id);
        Assert.notNull(po, () -> new CustomException(ErrorEnum.USER_DOES_NOT_EXIST));
        UserInfoVO vo = UserInfoVO.poConverVo(po);
        //查询角色
        List<RoleVO> roleVoList = this.userRolesService.getRoleVoByUserId(po.getId());
        vo.setRoleVoList(roleVoList);
        return vo;
    }

    @Override
    public void update(UpdateUserDTO param) {
        Users po = this.getById(param.getId());
        Assert.notNull(po, () -> new CustomException(ErrorEnum.USER_DOES_NOT_EXIST));
        po.setFullName(param.getFullName());
        po.setEmail(param.getEmail());
        po.setMobileNumber(param.getMobileNumber());
        po.setAvailableIp(param.getAvailableIp());
        this.updateById(po);
        //更新角色
        this.userRolesService.deleteByUserId(po.getId());
        this.userRolesService.batchInsert(po.getId(), param.getRoleIds());
    }

    @Override
    public List<PermissionTreeNodeVO> getPermissionTreeByUsername(String name) {
        List<PermissionTreeNodeVO> result = Lists.newArrayList();
        Users user = getUserByUsername(name);
        List<RoleVO> roleVoList = this.userRolesService.getRoleVoByUserId(user.getId());
        if (CollectionUtil.isEmpty(roleVoList)) {
            return result;
        }
        List<Long> roleIds = roleVoList.stream().map(it -> it.getId()).distinct().collect(Collectors.toList());
        return this.rolePermissionsService.getPermissionTreeByRoleIds(roleIds);
    }

    @Override
    public void deleteById(Long id) {
        //根据id查询
        Users po = this.getById(id);
        if (ObjectUtil.isNull(po)) {
            throw new CustomException(ErrorEnum.USER_DOES_NOT_EXIST);
        }
        //删除用户
        this.removeById(id);
        //查询用户角色关联表
        List<UserRoles> userRoles = this.userRolesMapper.selectList(new LambdaQueryWrapper<UserRoles>().eq(UserRoles::getUserId, id));
        //删除用户角色关联表
        if (CollectionUtil.isNotEmpty(userRoles)) {
            this.userRolesMapper.delete(new LambdaQueryWrapper<UserRoles>().eq(UserRoles::getUserId, id));
        }

    }


    private Users getUserByUsername(String username) {
        Users po = this.getOne(new LambdaQueryWrapper<Users>().eq(Users::getUsername, username));
        Assert.notNull(po, () -> new CustomException(ErrorEnum.USER_DOES_NOT_EXIST));
        return po;
    }


}
